#ifndef __ASIO_TCP_ACCEPTOR_IMPL_HPP__
#define __ASIO_TCP_ACCEPTOR_IMPL_HPP__

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <string>
#include <vector>
#include <memory>
#include "../tcp_acceptor_config.h"
#include "../io_handler.h"

#define TCP_SERVER_DEFAULT_PORT  8000

namespace vpm 
{
	namespace mina
	{
		using boost::asio::ip::tcp;	

		template <class T> 
		class AsioTcpAcceptorImpl 
		{
			public:

				AsioTcpAcceptorImpl(TcpAcceptorConfig& config, IoHandler & handler): 
					m_tcpAcceptorConfig(config),m_ioHandler(handler)
				{
				}

				virtual ~AsioTcpAcceptorImpl()
				{
				}

				int bind( int port = TCP_SERVER_DEFAULT_PORT, const std::string & host="0.0.0.0")			
				{
					std::cout << "Start boost asio tcp server "<<host << ":"<< port << std::endl ;

					m_pTcpAcceptor.reset(new tcp::acceptor(m_ioService,
								tcp::endpoint(boost::asio::ip::address::from_string(host),port)));

					boost::asio::socket_base::reuse_address opt(true); 
					m_pTcpAcceptor->set_option(opt);
					T* pTcpHandler = this->create_handler(); 
					pTcpHandler->create_socket(m_ioService);
					m_pTcpAcceptor->async_accept(pTcpHandler->socket(),
							boost::bind(&AsioTcpAcceptorImpl<T>::handle_accept, this, 
								pTcpHandler, boost::asio::placeholders::error));

					//boost::thread thr_service(ServiceTask(m_ioService));
                    boost::thread srv_thread(boost::bind(&boost::asio::io_service::run, &m_ioService));
					return 0; 
				}

				void unbind()
				{
				}


				virtual T *create_handler() 
				{				
					return new T(m_ioHandler,m_tcpAcceptorConfig);		
				}

				void handle_accept(T *pTcpSession, const boost::system::error_code& error)
				{
					if (!error)
					{
                        std::cout <<"A new session opened\n";
						pTcpSession->open(); 
						T* pTcpHandler = create_handler();
						pTcpHandler->create_socket(m_ioService);
						m_pTcpAcceptor->async_accept(pTcpHandler->socket(),
								boost::bind(&AsioTcpAcceptorImpl<T>::handle_accept, this, 
									pTcpHandler, boost::asio::placeholders::error));
					}
				}

				boost::asio::io_service & io_service()
				{
					return m_ioService;
				}


			private:		

				TcpAcceptorConfig &m_tcpAcceptorConfig;	
				IoHandler & m_ioHandler;

				std::string m_host; 
				int         m_port;
				boost::asio::io_service  m_ioService ; 
				std::auto_ptr<tcp::acceptor> m_pTcpAcceptor; 
		};

#define  TcpAcceptorImpl AsioTcpAcceptorImpl
	}
}



#endif
